package com.zoe.onelink.feign.interceptor;

import com.zoe.onelink.common.constant.OnelinkFeignConstant;
import com.zoe.onelink.common.constant.RpcClient;
import com.zoe.onelink.common.constant.RpcConstant;
import com.zoe.onelink.core.autoconfigure.OnelinkI18nAutoConfiguration;
import com.zoe.onelink.feign.auth.token.FeignTokenEncryptor;
import com.zoe.onelink.feign.property.OnelinkFeignProperties;
import com.zoe.onelink.util.OnelinkContextHolder;
import com.zoe.onelink.util.SpringUtil;
import com.zoe.onelink.util.StrUtil;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.core.annotation.Order;

import javax.servlet.http.HttpServletRequest;
import java.util.Set;

/**
 * <p>标题: Feign请求拦截器</p>
 * <p>描述: </p>
 * <p>版权: Copyright (c) 2021</p>
 * <p>公司: 智业软件股份有限公司</p>
 *
 * @version: 1.0
 * @author: ruansheng
 * @date: 2021-08-03
 */
@RequiredArgsConstructor
@Order(2000)
public class FeignRequestInterceptor implements RequestInterceptor {

    private final FeignTokenEncryptor feignTokenEncryptor;
    private final OnelinkFeignProperties.Request requestProp;
    private static final Set<String> DEFAULT_TRANS_HEADERS = Set.of(
            "operator", "deptCode", "districtCode", "orgCode", "clientIp"
    );

    @Value("${spring.application.name:}")
    private String applicationName;

    @Override
    public void apply(RequestTemplate requestTemplate) {
        // 解决: Incomplete output stream executing POST 问题
        requestTemplate.removeHeader("Content-Length");
        // 转发原始请求头信息
        this.transferOriginalHeaders(requestTemplate);
        requestTemplate.header(OnelinkFeignConstant.APPLICATION_NAME, applicationName);
        // 增加RPC客户端标识
        requestTemplate.header(RpcConstant.RPC_CLIENT_HEADER_NAME, RpcClient.FEIGN.name());
        // 国际化
        requestTemplate.header(OnelinkI18nAutoConfiguration.LOCALE_REQUEST_PARAM, LocaleContextHolder.getLocale().getLanguage());
        // 设置内部请求Token
        requestTemplate.header(OnelinkFeignConstant.TOKEN_HEADER_NAME, this.feignTokenEncryptor.encrypt());
    }

    /**
     * 转发原始请求头信息
     */
    private void transferOriginalHeaders(RequestTemplate requestTemplate) {
        HttpServletRequest request = SpringUtil.getRequest();
        if (request == null) {
            return;
        }
        for (String defaultTransHeader : DEFAULT_TRANS_HEADERS) {
            String headerValue = StrUtil.blankToDefault(request.getHeader(defaultTransHeader), OnelinkContextHolder.getString(defaultTransHeader));
            requestTemplate.header(defaultTransHeader, headerValue);
        }
        for (String transferHeader : this.requestProp.getTransferHeaders()) {
            requestTemplate.header(transferHeader, request.getHeader(transferHeader));
        }
    }

}
